package com.sparrow.common.util;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 随机数工具类
 */
public class RandomUtil {

    /**
     * 生成一个介于 0（包含）到指定边界（不包含）之间的随机整数。
     */
    public static int nextInt(int bound) {
        return ThreadLocalRandom.current().nextInt(bound);
    }

    public static float nextFloat() {
        return ThreadLocalRandom.current().nextFloat();
    }


    public static float nextFloat(float origin, float bound) {
        if (origin >= bound) {
            throw new IllegalArgumentException("origin must be less than bound");
        }
        return ThreadLocalRandom.current().nextFloat() * (bound - origin) + origin;
    }

    /**
     * min-bound之间的随机
     */
    public static int nextIntBetween(int min, int bound) {
        if (min > bound) {
            throw new IllegalArgumentException("最小值不能大于最大值，min: " + min + ", bound: " + bound);
        }
        if (min == bound) {
            return min;
        }
        return nextInt(bound - min + 1) + min;
    }

    /**
     * 根据权重从给定的元素列表中随机选择一个元素。
     */
    public static <T extends WeightObj> T randomlySelectElementByWeight(List<T> weightList) {
        if (weightList.isEmpty()) {
            throw new IllegalArgumentException("权重列表不能为空");
        }
        int sum = weightList.stream().mapToInt(WeightObj::getWeight).sum();
        int val = nextIntBetween(1, sum);
        int cur = 0;
        for (T obj : weightList) {
            cur += obj.getWeight();
            if (val <= cur) {
                return obj;
            }
        }
        throw new IllegalStateException("未能根据权重选择到元素，可能是代码逻辑错误");
    }


    /**
     * 从 List<int[]> 中按权重随机选择一个元素
     *
     * @param dataList    每个元素是 int[]，例如 [id, count, weight]
     * @param weightIndex 表示权重在 int[] 中的下标
     * @return 随机选择到的 int[] 元素
     */
    public static int[] randomlySelectByWeight(List<int[]> dataList, int weightIndex) {
        if (dataList == null || dataList.isEmpty()) {
            throw new IllegalArgumentException("权重列表不能为空");
        }
        // 计算权重总和
        int totalWeight = 0;
        for (int[] arr : dataList) {
            int weight = arr[weightIndex];
            totalWeight += weight;
        }
        if (totalWeight <= 0) {
            throw new IllegalArgumentException("权重总和必须大于 0");
        }
        // 生成随机值（1 ~ totalWeight）
        int rand = nextIntBetween(1, totalWeight);
        // 按区间查找
        int cur = 0;
        for (int[] arr : dataList) {
            cur += arr[weightIndex];
            if (rand <= cur) {
                return arr;
            }
        }
        throw new IllegalStateException("未能根据权重选择到元素，逻辑错误");
    }


    /**
     * 具有权重属性的对象接口。
     */
    public interface WeightObj {
        /**
         * 获取对象的权重。
         *
         * @return 对象的权重值。
         */
        int getWeight();
    }

    /**
     * Fisher–Yates 洗牌算法，用于打乱数组内容。
     * 等概率随机打乱数组中所有元素。
     */
    public static void shuffle(int[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            int j = ThreadLocalRandom.current().nextInt(i + 1);
            int tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
        }
    }

    /**
     * 泛型版本：打乱 List 元素
     */
    public static <T> void shuffle(List<T> list) {
        for (int i = list.size() - 1; i > 0; i--) {
            int j = ThreadLocalRandom.current().nextInt(i + 1);
            T tmp = list.get(i);
            list.set(i, list.get(j));
            list.set(j, tmp);
        }
    }

    /**
     * 从[min, max]中随机选取count个不重复整数（包含边界）
     */
    public static int[] randomUniqueInt(int min, int max, int count) {
        if (min > max) {
            throw new IllegalArgumentException("min不能大于max");
        }
        int n = max - min + 1;
        if (count > n) {
            throw new IllegalArgumentException("count不能大于范围大小");
        }
        List<Integer> list = new ArrayList<>(n);
        for (int i = min; i <= max; i++) {
            list.add(i);
        }
        Collections.shuffle(list);
        int[] result = new int[count];
        for (int i = 0; i < count; i++) {
            result[i] = list.get(i);
        }
        return result;
    }

    public static <T> List<T> randomElements(List<T> list, int count) {
        if (count > list.size()) {
            throw new IllegalArgumentException("count不能大于列表长度");
        }
        List<T> copy = new ArrayList<>(list);
        Collections.shuffle(copy);
        return copy.subList(0, count);
    }

    /**
     * 从列表中随机选取不重复的元素（基于 equals() 判重）。
     * @param list 原始列表（可包含重复元素）
     * @param count 需要的随机元素数量
     * @return 不重复随机元素的列表
     */
    public static <T> List<T> randomUniqueElements(List<T> list, int count) {
        if (list == null || list.isEmpty()) {
            throw new IllegalArgumentException("列表不能为空");
        }

        // 1️⃣ 先用 LinkedHashSet 去重，保留原顺序 + equals 判重
        Set<T> uniqueSet = new LinkedHashSet<>(list);
        List<T> uniqueList = new ArrayList<>(uniqueSet);

        if (count > uniqueList.size()) {
            throw new IllegalArgumentException("请求的数量超出不重复元素个数");
        }

        // 2️⃣ 洗牌（Fisher–Yates 算法）
        for (int i = uniqueList.size() - 1; i > 0; i--) {
            int j = RandomUtil.nextInt(i + 1);
            Collections.swap(uniqueList, i, j);
        }

        // 3️⃣ 返回前 count 个
        return uniqueList.subList(0, count);
    }

    public static void main(String[] args) {
        float v = nextFloat(1.0f, 2.f);
        System.out.println(v);
    }

}